﻿using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using static WCAD.Jigs;

namespace WCAD
{
    public static class PmPolylineMethod
    {
        public static List<Curve> ExplodePolyline(this Polyline polyline)
        {
            DBObjectCollection dbs = new DBObjectCollection();
            polyline.Explode(dbs);
            List<Curve> curves = new List<Curve>();
            foreach (Curve item in dbs)
            {
                curves.Add(item);
            }
            return curves;
        }
        public static Polyline CreatePolylineByExtents3d(Extents3d extents)
        {
            Polyline pl = new Polyline();
            pl.AddVertexAt(0, new Point2d(extents.MinPoint.X, extents.MinPoint.Y), 0, 0, 0);
            pl.AddVertexAt(1, new Point2d(extents.MaxPoint.X, extents.MinPoint.Y), 0, 0, 0);
            pl.AddVertexAt(2, new Point2d(extents.MaxPoint.X, extents.MaxPoint.Y), 0, 0, 0);
            pl.AddVertexAt(3, new Point2d(extents.MinPoint.X, extents.MaxPoint.Y), 0, 0, 0);
            pl.Closed = true;
            return pl;
        }
        public static Polyline CreatePolylineByExtents3d(Extents3d extents,double r)
        {
            Polyline pl = new Polyline();
            double b = (1 - Math.Sqrt(2) / 2) / (Math.Sqrt(2) / 2);
            double w=extents.MaxPoint.X - extents.MinPoint.X;
            double h = extents.MaxPoint.Y - extents.MinPoint.Y;
            Point2d point = extents.MinPoint.ToPoint2d();
            point += new Vector2d(r, 0);
            pl.AddVertexAt(0, point, 0, 0, 0);
            point += new Vector2d(w-r*2, 0);
            pl.AddVertexAt(1, point, b, 0, 0);
            point += new Vector2d(r, r);
            pl.AddVertexAt(2, point, 0, 0, 0);
            point += new Vector2d(0, h-r*2);
            pl.AddVertexAt(3, point, b, 0, 0);
            point += new Vector2d(-r, r);
            pl.AddVertexAt(4, point, 0, 0, 0);
            point += new Vector2d(-w + r * 2,0);
            pl.AddVertexAt(5, point, b, 0, 0);
            point += new Vector2d(-r, -r);
            pl.AddVertexAt(6, point, 0, 0, 0);
            point += new Vector2d(0, -h+2*r);
            pl.AddVertexAt(7, point, b, 0, 0);
            //point += new Vector2d(r, -r);
            //pl.AddVertexAt(8, point, 0, 0, 0);
            pl.Closed = true;
            return pl;
        }
        public static Polyline CreatePolyline(List<Point3d> points, bool isClosed = true)
        {
            Polyline pl = new Polyline();
            for (int i = 0; i < points.Count; i++)
            {
                pl.AddVertexAt(i, points[i].Convert2d(new Plane()), 0, 0, 0);
            }
            pl.Closed = isClosed;
            return pl;
        }
        public static Polyline CreatePolyline(List<Point2d> points, bool isClosed = true)
        {
            Polyline pl = new Polyline();
            for (int i = 0; i < points.Count; i++)
            {
                pl.AddVertexAt(i, points[i], 0, 0, 0);
            }
            pl.Closed = isClosed;
            return pl;
        }
        public static Polyline3d CreatePolyline3d(List<Point3d> points, bool isClosed = true)
        {
            Poly3dType poly3DType = Poly3dType.SimplePoly;
            Point3dCollection point3DCollection = new Point3dCollection();
            points.ForEach(x => point3DCollection.Add(x));
            Polyline3d polyline3D = new Polyline3d(poly3DType, point3DCollection, isClosed);
            return polyline3D;
        }
        public static List<Point2d> GetPoint2ds(this Polyline polyline)
        {
            List<Point2d> points = new List<Point2d>();
            for (int i = 0; i < polyline.NumberOfVertices; i++)
            {
                points.Add(polyline.GetPoint2dAt(i));
            }
            return points;
        }
        public static Point2dCollection GetPoint2dCollection(this Polyline polyline)
        {
            Point2dCollection points = new Point2dCollection();
            for (int i = 0; i < polyline.NumberOfVertices; i++)
            {
                points.Add(polyline.GetPoint2dAt(i));
            }
            return points;
        }
        public static List<Point3d> GetPoint3ds(this Polyline polyline)
        {
            List<Point3d> points = new List<Point3d>();
            for (int i = 0; i < polyline.NumberOfVertices; i++)
            {
                points.Add(polyline.GetPoint3dAt(i));
            }
            return points;
        }
        /// <summary>
        /// 延长多段线其中一段（只适用于全直线的多段线）
        /// </summary>
        /// <param name="polyline"></param>
        /// <param name="num">节点索引</param>
        /// <param name="dis">延长长度</param>
        public static void ExtendPolyline(Polyline polyline, int num, double dis)
        {
            List<Point2d> points = polyline.GetPoint2ds();
            if (num > points.Count - 1) return;
            CompositeCurve3d curve3D = polyline.GetGeCurve() as CompositeCurve3d;
            Curve3d curve = curve3D.GetCurves()[num == 0 ? 1 : num - 1];
            if (curve is CircularArc3d arc && num > 0)
            {
                Point3d center = arc.Center;
                double radius = arc.Radius;
                double ro = dis / radius;
                if (arc.Normal.Z < 0) ro = Math.PI * 2 - ro;
                for (int i = num; i < points.Count; i++)
                {
                    if (i == 0) continue;
                    points[i] = points[i].RotateBy(ro, center.Convert2d(new Plane()));
                }
                Vector3d vector1 = center.GetVectorTo(points[num - 1].ToPoint3d());
                Vector3d vector2 = center.GetVectorTo(points[num].ToPoint3d());
                double bu = Math.Tan(vector1.GetAngleTo(vector2, arc.Normal) / 4);
                if (arc.Normal.Z < 0) bu *= -1;
                polyline.SetBulgeAt(num - 1, bu);
            }
            else
            {
                Point3d point3d = polyline.GetPointAtParameter(num - (num > 0 ? 0.1 : 0));
                Vector2d vector = polyline.GetFirstDerivative(point3d).Convert2d(new Plane());
                vector = vector.GetNormal() * dis;
                for (int i = num; i < points.Count; i++)
                {
                    if (i == 0) continue;
                    points[i] += vector;
                }
            }

            for (int i = 0; i < points.Count; i++)
            {
                if (i == 0) continue;
                polyline.SetPointAt(i, points[i]);
            }

        }
        public static List<Curve> GetYoushouByVector(Point3d point, Vector3d vector)
        {
            List<Curve> curves = new List<Curve>();
            Vector3d vector1 = -vector.RotateBy(Math.PI / 6, Vector3d.YAxis) / 10;
            Vector3d vector2 = -vector.RotateBy(Math.PI / 6, -Vector3d.YAxis) / 10;
            Point3d p1 = point + vector + vector1;
            Point3d p2 = point + vector + vector2;
            List<Point3d> points = new List<Point3d>();
            points.Add(point);
            points.Add(point + vector);
            points.Add(p1);
            points.Add(point + vector);
            points.Add(p2);
            points.Add(point + vector);
            Polyline3d pl = PmPolylineMethod.CreatePolyline3d(points, false);

            Circle circle = new Circle(point, vector, vector.Length * 0.8);
            Point3d point1 = circle.GetPointAtDist(0);
            Point3d point2 = circle.GetPointAtDist(circle.Circumference/4);
            Point3d point3 = circle.GetPointAtDist(circle.Circumference / 2);
            Point3d point4 = circle.GetPointAtDist(circle.Circumference / 4*3);
            Vector3d v1 = circle.GetFirstDerivative(point1).GetNormal()* vector.Length/10;
            Vector3d v2 = circle.GetFirstDerivative(point2).GetNormal() * vector.Length / 10;
            Vector3d v3 = circle.GetFirstDerivative(point3).GetNormal() * vector.Length / 10;
            Vector3d v4 = circle.GetFirstDerivative(point4).GetNormal() * vector.Length / 10;
            Line line11 = new Line(point1, point1 + v1.RotateBy(Math.PI * 5 / 6, Vector3d.ZAxis));
            Line line12 = new Line(point1, point1 + v1.RotateBy(Math.PI * 5 / 6, -Vector3d.ZAxis));
            Line line21 = new Line(point2, point2 + v2.RotateBy(Math.PI * 5 / 6, Vector3d.ZAxis));
            Line line22 = new Line(point2, point2 + v2.RotateBy(Math.PI * 5 / 6, -Vector3d.ZAxis));
            Line line31 = new Line(point3, point3 + v3.RotateBy(Math.PI * 5 / 6, Vector3d.ZAxis));
            Line line32 = new Line(point3, point3 + v3.RotateBy(Math.PI * 5 / 6, -Vector3d.ZAxis));
            Line line41 = new Line(point4, point4 + v4.RotateBy(Math.PI * 5 / 6, Vector3d.ZAxis));
            Line line42 = new Line(point4, point4 + v4.RotateBy(Math.PI * 5 / 6, -Vector3d.ZAxis));
            curves.Add(pl);
            curves.Add(circle);
            curves.Add(line11);
            curves.Add(line12);
            curves.Add(line21);
            curves.Add(line22);
            curves.Add(line31);
            curves.Add(line32);
            curves.Add(line41);
            curves.Add(line42);

            return curves;
        }
        public static bool IsPointInPolyline(this Point3d point,Polyline pl)
        {
            MPolygon mPolygon = new MPolygon();//需要引用AcMPolygonMGD.dll也在cad安装路径
            mPolygon.AppendLoopFromBoundary(pl, false, 0);
            return mPolygon.IsPointInsideMPolygon(point, 0).Count == 1;
        }
        
    }
}
